import { spawn, ChildProcess } from 'child_process';
import { MCPServerConfig, MCPConfig, Interruptible, ToolCall, ToolResult } from '../types';
import { interruptController } from './interruptController';

/**
 * MCP服务器状态
 */
export type MCPServerStatus = 'stopped' | 'starting' | 'running' | 'error';

/**
 * MCP服务器实例
 */
export interface MCPServerInstance {
  id: string;
  config: MCPServerConfig;
  process?: ChildProcess;
  status: MCPServerStatus;
  error?: string;
  tools: Array<{
    name: string;
    description?: string;
    parameters?: any;
  }>;
  lastHeartbeat?: Date;
}

/**
 * 工具调用请求
 */
export interface ToolCallRequest {
  serverId: string;
  toolName: string;
  parameters: Record<string, any>;
  timeout?: number;
}

/**
 * MCP管理器 - 管理所有MCP服务器实例
 */
class MCPManager implements Interruptible {
  private servers: Map<string, MCPServerInstance> = new Map();
  private isRegistered = false;
  private toolCallCounter = 0;
  private activeToolCalls: Map<string, { 
    request: ToolCallRequest; 
    startTime: Date; 
    resolve: (result: any) => void;
    reject: (error: Error) => void;
  }> = new Map();

  constructor() {
    this.registerWithInterruptController();
  }

  /**
   * 注册到中断控制器
   */
  private registerWithInterruptController(): void {
    if (!this.isRegistered) {
      interruptController.addInterruptible(this);
      this.isRegistered = true;
    }
  }

  /**
   * 实现Interruptible接口
   */
  async interrupt(reason?: string): Promise<void> {
    console.log(`MCP管理器中断: ${reason || '用户中断'}`);
    
    // 中断所有活跃的工具调用
    const interruptPromises = Array.from(this.activeToolCalls.entries()).map(
      ([callId, callInfo]) => {
        callInfo.reject(new Error(`工具调用被中断: ${reason || '用户中断'}`));
        return this.cancelToolCall(callId);
      }
    );

    await Promise.allSettled(interruptPromises);
    this.activeToolCalls.clear();
  }

  /**
   * 检查是否正在中断
   */
  isInterrupting(): boolean {
    return interruptController.isInterrupting();
  }

  /**
   * 初始化MCP服务器
   */
  async initializeFromConfig(config: MCPConfig): Promise<void> {
    const startPromises = Object.entries(config.mcpServers).map(
      ([serverId, serverConfig]) => this.startServer(serverId, serverConfig)
    );

    await Promise.allSettled(startPromises);
  }

  /**
   * 启动MCP服务器
   */
  async startServer(serverId: string, config: MCPServerConfig): Promise<void> {
    const instance: MCPServerInstance = {
      id: serverId,
      config,
      status: 'starting',
      tools: []
    };

    this.servers.set(serverId, instance);

    try {
      // 启动进程
      const process = spawn(config.command, config.args, {
        env: { ...process.env, ...config.env },
        stdio: ['pipe', 'pipe', 'pipe']
      });

      instance.process = process;

      // 监听进程事件
      process.on('error', (error) => {
        instance.status = 'error';
        instance.error = error.message;
        console.error(`MCP服务器 ${serverId} 启动失败:`, error);
      });

      process.on('exit', (code) => {
        instance.status = 'stopped';
        console.log(`MCP服务器 ${serverId} 退出，代码: ${code}`);
      });

      // 解析服务器输出以获取工具列表
      await this.discoverTools(instance);

      instance.status = 'running';
      instance.lastHeartbeat = new Date();
      
      console.log(`MCP服务器 ${serverId} 启动成功`);
    } catch (error) {
      instance.status = 'error';
      instance.error = error instanceof Error ? error.message : '未知错误';
      console.error(`启动MCP服务器 ${serverId} 失败:`, error);
    }
  }

  /**
   * 发现服务器工具
   */
  private async discoverTools(instance: MCPServerInstance): Promise<void> {
    // 这里应该通过MCP协议与服务器通信获取工具列表
    // 为简化实现，暂时模拟一些工具
    if (instance.id === 'File-Operations') {
      instance.tools = [
        { name: 'read_file', description: '读取文件内容' },
        { name: 'write_file', description: '写入文件内容' },
        { name: 'list_directory', description: '列出目录内容' },
        { name: 'create_directory', description: '创建目录' },
        { name: 'delete_file', description: '删除文件' }
      ];
    }
  }

  /**
   * 调用工具
   */
  async callTool(request: ToolCallRequest): Promise<any> {
    const server = this.servers.get(request.serverId);
    if (!server) {
      throw new Error(`MCP服务器 ${request.serverId} 不存在`);
    }

    if (server.status !== 'running') {
      throw new Error(`MCP服务器 ${request.serverId} 状态异常: ${server.status}`);
    }

    const callId = `tool_call_${++this.toolCallCounter}`;
    const timeout = request.timeout || 30000; // 默认30秒超时

    return new Promise((resolve, reject) => {
      // 记录活跃的工具调用
      this.activeToolCalls.set(callId, {
        request,
        startTime: new Date(),
        resolve,
        reject
      });

      // 设置超时
      const timeoutId = setTimeout(() => {
        this.activeToolCalls.delete(callId);
        reject(new Error(`工具调用超时: ${request.toolName}`));
      }, timeout);

      // 模拟工具调用（实际应该通过MCP协议与服务器通信）
      this.executeToolCall(callId, request)
        .then((result) => {
          clearTimeout(timeoutId);
          this.activeToolCalls.delete(callId);
          resolve(result);
        })
        .catch((error) => {
          clearTimeout(timeoutId);
          this.activeToolCalls.delete(callId);
          reject(error);
        });
    });
  }

  /**
   * 执行工具调用（模拟实现）
   */
  private async executeToolCall(callId: string, request: ToolCallRequest): Promise<any> {
    // 模拟延迟
    await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 2000));

    // 检查是否被中断
    if (this.isInterrupting()) {
      throw new Error('工具调用被中断');
    }

    // 模拟不同工具的执行结果
    switch (request.toolName) {
      case 'read_file':
        return {
          content: `文件内容: ${request.parameters.path}`,
          size: 1024
        };
      case 'write_file':
        return {
          success: true,
          bytesWritten: request.parameters.content?.length || 0
        };
      case 'list_directory':
        return {
          files: ['file1.txt', 'file2.txt', 'subdirectory/'],
          count: 3
        };
      default:
        throw new Error(`不支持的工具: ${request.toolName}`);
    }
  }

  /**
   * 取消工具调用
   */
  private async cancelToolCall(callId: string): Promise<void> {
    const callInfo = this.activeToolCalls.get(callId);
    if (callInfo) {
      // 这里应该向MCP服务器发送取消请求
      console.log(`取消工具调用: ${callId}`);
    }
  }

  /**
   * 获取服务器状态
   */
  getServerStatus(serverId: string): MCPServerInstance | undefined {
    return this.servers.get(serverId);
  }

  /**
   * 获取所有服务器状态
   */
  getAllServers(): MCPServerInstance[] {
    return Array.from(this.servers.values());
  }

  /**
   * 获取可用工具列表
   */
  getAvailableTools(): Array<{ serverId: string; toolName: string; description?: string }> {
    const tools: Array<{ serverId: string; toolName: string; description?: string }> = [];
    
    for (const server of this.servers.values()) {
      if (server.status === 'running') {
        for (const tool of server.tools) {
          tools.push({
            serverId: server.id,
            toolName: tool.name,
            description: tool.description
          });
        }
      }
    }
    
    return tools;
  }

  /**
   * 停止服务器
   */
  async stopServer(serverId: string): Promise<void> {
    const server = this.servers.get(serverId);
    if (server && server.process) {
      server.process.kill();
      server.status = 'stopped';
    }
  }

  /**
   * 停止所有服务器
   */
  async stopAllServers(): Promise<void> {
    const stopPromises = Array.from(this.servers.keys()).map(
      serverId => this.stopServer(serverId)
    );
    await Promise.allSettled(stopPromises);
  }

  /**
   * 清理资源
   */
  async cleanup(): Promise<void> {
    await this.stopAllServers();
    this.activeToolCalls.clear();
    this.servers.clear();
    
    if (this.isRegistered) {
      interruptController.removeInterruptible(this);
      this.isRegistered = false;
    }
  }
}

// 导出单例
export const mcpManager = new MCPManager();